package main

import (
	"01/errhandling/filelisting/listing"
	"log"
	"net/http"
	"os"
)

// 定义一个函数类型, 返回 error
type appHandler func(writer http.ResponseWriter,
	request *http.Request) error

// 再定义一个函数，功能是返回 HandleFunc()参数需要的函数
func errWrapper(
	handler appHandler) func(
		http.ResponseWriter, *http.Request) {
	return func(writer http.ResponseWriter, 
	request *http.Request) {
		defer func() {
			if r != nil {
				r := recover()
				log.Printf("Panic: %v", r)
				http.Error(writer,
					http.StatusText(http.StatusInternalServerError), // 返回服务器出错状态码
					http.StatusInternalServerError)
			}
		}()
		err := handler(writer, request)
		if err != nil {
			code := http.StatusOK
			switch {
			// 如果是文件不存在的错误
			case os.IsNotExist(err):
				http.Error(writer, http.StatusText(http.StatusNotFound), http.StatusNotFound)
				code = http.StatusNotFound
			// 没权限
			case os.IsPermission(err):
				code = http.StatusForbidden
			// 默认
			default:
				code = http.StatusInternalServerError
			}

			http.Error(writer,
			http.StatusText(code), code)
		}   
	}
}


// 实现一个显示文件的 webserver
func main() {
	http.HandleFunc("/", errWrapper(listing.HandFileList))  // 处理逻辑函数，抽象出来
	err := http.ListenAndServe(":8888", nil)
	if err != nil {
		panic(err)
	}
}
